package club.xyes.zkh.ecommerce.service.impl;

import club.xyes.zkh.ecommerce.commons.context.ApplicationConstants;
import club.xyes.zkh.ecommerce.commons.entity.User;
import club.xyes.zkh.ecommerce.commons.exception.InternalServerErrorException;
import club.xyes.zkh.ecommerce.commons.exception.ResourceNotFoundException;
import club.xyes.zkh.ecommerce.commons.properties.WechatConfigurationProperties;
import club.xyes.zkh.ecommerce.dao.mapper.UserMapper;
import club.xyes.zkh.ecommerce.service.UserService;
import club.xyes.zkh.ecommerce.wechat.dto.Code2SessionResult;
import club.xyes.zkh.ecommerce.wechat.dto.WxOauth2AccessTokenResult;
import club.xyes.zkh.ecommerce.wechat.dto.WxUserInfoResult;
import club.xyes.zkh.ecommerce.wechat.service.WeChatService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.io.IOException;
import java.util.List;
import java.util.Optional;

/**
 * Create by 郭文梁 2019/4/15 0015 15:22
 * UserServiceImpl
 * 用户业务服务组件实现
 *
 * @author 郭文梁
 * @data 2019/4/15 0015
 */
@Service
public class UserServiceImpl extends BaseServiceImpl<User> implements UserService {
    private static final String DEFAULT_AVATAR = "http://zkh-cdn.xyes.club/xbb/user/default.png";
    private final UserMapper mapper;

    private final WeChatService weChatService;
    private final WechatConfigurationProperties wechatConfigurationProperties;

    @Autowired
    public UserServiceImpl(UserMapper mapper, WeChatService weChatService, WechatConfigurationProperties wechatConfigurationProperties) {
        super(mapper);
        this.mapper = mapper;
        this.weChatService = weChatService;
        this.wechatConfigurationProperties = wechatConfigurationProperties;
    }

    @Override
    public User loginByMicroProgramCode(String code) {
        //换取openid
        Code2SessionResult result = weChatService.code2Session(
                wechatConfigurationProperties.getUserMicroProgramAppId(),
                wechatConfigurationProperties.getUserMicroProgramSecret(),
                code
        );
        String openid = result.getOpenid();
        return loginByOpenId(openid, result.getSessionKey());
    }

    @Override
    public User loginByOpenId(String openId, String sessionKey) {
        //检查用户是否存在
        User user = findByOpenId(openId);
        if (user == null) {
            user = createUserByOpenId(openId, sessionKey);
        } else {
            user.setWxSessionKey(sessionKey);
            user = updateById(user);
        }
        return user;
    }

    @Override
    public User findByOpenId(String openId) {
        User query = new User();
        query.setWxOpenId(openId);
        return findOneByQuery(query);
    }

    @Override
    public User complementByOpenId(String openid, String avatar, String name) {
        User user = findByOpenId(openid);
        if (user == null) {
            throw new ResourceNotFoundException(User.class, openid);
        }
        user.setAvatar(avatar);
        user.setName(name);
        return updateById(user);
    }

    @Override
    public User setMobile(User user, String iv, String data) {
        WxUserInfoResult userInfo = weChatService.toUserInfo(user.getWxSessionKey(), iv, data);
        user.setMobile(userInfo.getPurePhoneNumber());
        return updateById(user);
    }

    @Override
    public User bindOauthOpenId(User user, String code) throws IOException {
        String appId = wechatConfigurationProperties.getServiceAccountAppId();
        String secret = wechatConfigurationProperties.getServiceAccountSecret();
        WxOauth2AccessTokenResult result = weChatService.oauth2CodeToken(appId, secret, code);
        if (!result.isSuccess()) {
            throw new InternalServerErrorException(result.getErrmsg());
        }
        String openid = result.getOpenid();
        user.setServiceWxOpenId(openid);
        return updateById(user);
    }

    @Override
    public List<User> findByIds(List<Integer> userIdList) {
        return mapper.selectByIds(joinAsString(userIdList, ","));
    }

    private String joinAsString(List<Integer> ids, String delimiter) {
        Optional<String> idList = ids.stream().map(String::valueOf).reduce((v1, v2) -> v1 + delimiter + v2);
        return idList.orElse("0");
    }

    /**
     * 创建用户
     *
     * @param openId     OpenId
     * @param sessionKey 会话
     * @return 用户对象
     */
    private User createUserByOpenId(String openId, String sessionKey) {
        User user = new User();
        user.setWxOpenId(openId);
        user.setName("微信用户");
        user.setAvatar(DEFAULT_AVATAR);
        user.setPassword(ApplicationConstants.Security.WECHAT_REGISTER_DEFAULT_PASSWORD);
        user.setExpired(false);
        user.setLocked(false);
        user.setCredentialsExpired(false);
        user.setEnabled(true);
        user.setWxSessionKey(sessionKey);
        return save(user);
    }
}
